package org.sensornet2010.co2sh.core;

/*
 * Thread object that performs the measurement. Reads the configuration from SensornetConfiguration.
 * An iSensornetAppListener is used for asynchronous interaction with this object.
 */
public class SensornetApp extends Thread {
	private String serverUrl;
	private int recordingInterval;
	private long recordingDuration;
	private long counter;
	private iSensornetAppListener listener;
	private boolean isRunning;

	SoundRecorder recorder;
	RemoteServer server;

	public SensornetApp() {
		this.serverUrl = SensornetConfiguration.SERVER_URL;
		this.recordingInterval = SensornetConfiguration.RECORDING_INTERVAL;
		this.recordingDuration = SensornetConfiguration.RECORDING_DURATION;
		this.recorder = new SoundRecorder(this.recordingDuration);
		this.server = new RemoteServer(this.serverUrl);
		this.isRunning = true;
	}
	
	public void setListener(iSensornetAppListener listener) {
		this.listener = listener;
	}

	private void notifyListener(int type, String info) {
		if (this.listener != null)
			this.listener.sensorAction(type, info);
	}

	public void stopApp(){
		this.isRunning = false;
	}
	
	public void run() {
		SensornetUtil.debug("SensornetApp:run() server=" + this.serverUrl);
		try {
			while (isRunning) {
				doMeasurement();
				if (!isRunning) break;
				long millis = this.recordingInterval * 1000 - this.recordingDuration;
				if (millis < 0) millis = 0;
				Thread.sleep(millis);
			}
		} catch (Exception e) {
			SensornetUtil.debugException(e);
		};
		this.notifyListener(iSensornetAppListener.APP_END, "");
	}

	/*
	 * This method performs the measurement process at configured intervals. 
	 */
	protected void doMeasurement() {
		SensornetUtil.debug("SensornetApp:doMeasurement()");
		this.notifyListener(iSensornetAppListener.MEASUREMENT_START, "");
		byte[] sound;
		try {
			String serverState = this.server.getState();
			if (serverState != null && !serverState.startsWith("OK"))
				this.notifyListener(iSensornetAppListener.ERROR_MSG, "Bad response from server: " + serverState);
			this.notifyListener(iSensornetAppListener.MEASUREMENT_SOUND_ACQ_START, "");
			// sound signal acquisition
			sound = this.recorder.record();
			this.notifyListener(iSensornetAppListener.MEASUREMENT_SOUND_ACQ_END, "");
			// sensor data encapsulation
			SensorData data = new SensorData(SensornetConfiguration.SENSOR_ID, sound, SensornetConfiguration.SENSUINO_VERSION);
			this.notifyListener(iSensornetAppListener.MEASUREMENT_SERVER_CONNECTION_START, "");
			// send data to server 
			String response = this.server.sendData(data);
			this.notifyListener(iSensornetAppListener.MEASUREMENT_SERVER_CONNECTION_END, "");
			//if (response != null && !response.startsWith("OK")){
			//	this.notifyListener(iSensornetAppListener.ERROR_MSG, "Bad response from server: " + response + " EXIT");
			//	throw new SensornetException(null, SensornetException.UNCONTROLED_ERROR, "Bad response from server:" + response + ". EXIT");
			//}
			this.notifyListener(iSensornetAppListener.MEASUREMENT_VALUE, ""+data.getCo2Value());
			this.counter++;
			
		} catch (Exception e){
			this.notifyListener(iSensornetAppListener.ERROR_MSG, e.getMessage());
			throw new SensornetException(e, SensornetException.UNCONTROLED_ERROR, e.getMessage());
		}
		this.notifyListener(iSensornetAppListener.MEASUREMENT_END, ""+this.counter);
		
	}

}
